package Net::FastScan;

use JIP::ToolSet; # load my commonly-used modules in a single import
use parent qw( Class::Base Class::Accessor::Fast );

use threads;
use threads::shared;
use Net::Ping;
use Carp qw( croak );
use Readonly qw( Readonly );
use English qw( -no_match_vars );

__PACKAGE__->mk_ro_accessors( qw( _maxThreads ) );

Readonly my $PING_TIMEOUT     => 1;
Readonly my $FTP_DEFAULT_PORT => 21;

my @_allServers    : shared;
my @_serversOnline : shared;

sub init {
    my( $self, $params ) = @ARG;

    $self->{'_maxThreads'} = $params->{'max_threads'}
        or croak 'required parameter "max_threads" not defined';

    return $self;
}

sub getActiveFTPServers {
    my $self = shift;

    @_allServers = @ARG;

    # fire and forget
    threads->create( \&_worker ) for 1 .. $self->_maxThreads;

    # waiting for a thread to exit
    foreach my $eachThread ( threads->list() ){ $eachThread->join }

    return @_serversOnline;
}

sub _worker {
    my $ping = Net::Ping->new('syn');

    $ping->port_number( $FTP_DEFAULT_PORT );

    while ('true') {
        my $IPAddress;

        # блокируется @_allServers
        # блокировка действует только внутри блока
        # блок максимально короткий и минималистичный
        {
            lock @_allServers;

            threads->exit unless @_allServers;

            $IPAddress = shift @_allServers;
        }

        $ping->ping( $IPAddress, $PING_TIMEOUT );

        if ( $ping->ack ) {
            lock @_serversOnline;

            push @_serversOnline, $IPAddress;
        }
    }
}

1;
